
package basicBcast;

import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import BEB.BebBroadcast;
import BEB.BebDeliver;
import BEB.BEB;

import se.kth.ict.id2203.pp2p.PerfectPointToPointLink;
import se.kth.ict.id2203.pp2p.Pp2pDeliver;
import se.kth.ict.id2203.pp2p.Pp2pSend;
import se.sics.kompics.ComponentDefinition;
import se.sics.kompics.Handler;
import se.sics.kompics.Kompics;
import se.sics.kompics.Negative;
import se.sics.kompics.Positive;
import se.sics.kompics.Start;
import se.sics.kompics.address.Address;

/**
 * The <code>SimpleUnreliableBroadcast</code> class.
 * 
 * @author Federico Piccinini <fpic@sics.se>
 */
public final class BasicBcast extends ComponentDefinition {

	Negative<BEB> beb =  provides(BEB.class);	
	Positive<PerfectPointToPointLink> pp2p = requires (PerfectPointToPointLink.class);

	private static final Logger logger = LoggerFactory
			.getLogger(BasicBcast.class);

	private Set<Address> neighborSet;
	private Address self;

	/**
	 * Instantiates a new application0.
	 */
	public BasicBcast() {
		subscribe(handleInit, control);
		subscribe(handleStart, control);
		subscribe(handleBebBroadcast, beb);
		subscribe(handleDeliver, pp2p);
	}

	Handler<BasicBcastInit> handleInit = new Handler<BasicBcastInit>() {
		public void handle(BasicBcastInit event) {
			logger.info("Received Init event");
			neighborSet = event.getNeighborSet();
			self = event.getSelf();
			neighborSet.add(self);
			//as specified in the algorithm, the message is broadcasted to 'self' as well
		}
	};

	Handler<Start> handleStart = new Handler<Start>() {
		public void handle(Start event) {
		}
	};

	
	Handler<BebBroadcast> handleBebBroadcast = new Handler<BebBroadcast> () {
		public void handle (BebBroadcast event) {
			for (Address neighbor : neighborSet) {
				trigger (new Pp2pSend(neighbor, event.getDeliverEvent()), pp2p);
			}
		}
	};
	
	Handler <Pp2pDeliver> handleDeliver = new Handler<Pp2pDeliver> () {
		public void handle (Pp2pDeliver event) {
			if (event instanceof BebDeliver) {
				BebDeliver bebDeliver = (BebDeliver) event;
				trigger (bebDeliver, beb);
			}
		}
	};
	
	@SuppressWarnings("unused")
	private void doShutdown() {
		System.out.println("2DIE");
		System.out.close();
		System.err.close();
		Kompics.shutdown();
	}
}
